﻿using System;
using System.ServiceProcess;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Neo4jRestSharp.Neo4jJsonServices;
using Neo4jRestSharp.Neo4jRestServices;
using Newtonsoft.Json.Linq;
using NUnit.Framework;

namespace Neo4jRestSharp.Test.Neo4jJsonServices
{
    [TestFixture]
    public class NodeJsonTests : BaseServicesTest
    {        
        private readonly Uri neo4jRestUri = new Uri("http://localhost:9999/");
        private const string ROOT_INDEX = "http://localhost:9999/index";
        private const string ROOT_NODE = "http://localhost:9999/node";
        private const string REFERENCE_NODE = "http://localhost:9999/node/0";
        private int counter = 1;    
        
        [Test]
        public void GetRoodNode()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //get root node
            JObject rootNode = jsonServices.GetRootNode();

            //parse and validate each item
            Assert.AreEqual(rootNode.Count, 3);

            JToken token;
            rootNode.TryGetValue("index", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Value<string>(), ROOT_INDEX);
            
            rootNode.TryGetValue("node", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Value<string>(), ROOT_NODE);
            
            rootNode.TryGetValue("reference node", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Value<string>(), REFERENCE_NODE);
        }

		[Test]
		public void CreateEmptyNode()
		{
			var jsonServices = new NodeJsonServices(neo4jRestUri);

			//create node and get return json
			JObject jObject = jsonServices.CreateNode();
			Assert.AreEqual(jObject.Count, 12);
			Assert.AreEqual(jObject["data"].Value<JToken>().Count(), 0);
		}

        [Test]
        public void CreateNode()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create person and get JObject
            Person morpheus = base.CreatePerson<Person>(NODE1_NAME, NODE1_TITLE);
			JObject props = new JObject();
			foreach (var kvp in morpheus.GetProperties())
			{
				props.Add(kvp.Key, new JValue(kvp.Value));
			}
			
            //create node for person
            JObject jObject = jsonServices.CreateNode(props);

            //validate
            Assert.AreEqual(jObject.Count, 12);
            JToken token;
            jObject.TryGetValue("data", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Count(), 2);
            Assert.AreEqual(token[MatrixPerson.NAME].Value<string>(), NODE1_NAME);
            Assert.AreEqual(token[MatrixPerson.TITLE].Value<string>(), NODE1_TITLE);
        }

        [Test]
        public void GetNode()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //get the person
            JObject jObject = jsonServices.GetNode(morpheus.Id);

            //validate node properties
            Assert.AreEqual(jObject.Count, 12);
            JToken token;
            jObject.TryGetValue("data", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Count(), 4);
            Assert.AreEqual(token[MatrixPerson.NAME].Value<string>(), NODE1_NAME);
            Assert.AreEqual(token[MatrixPerson.TITLE].Value<string>(), NODE1_TITLE);
            Assert.AreEqual(token[MatrixPerson.ISHUMAN].Value<bool>(), morpheus.IsHuman);
            Assert.AreEqual(token[MatrixPerson.ISAGENT].Value<bool>(), morpheus.IsAgent);
        }

        [Test]
        public void SetNodeProperties()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //change title and validate
            morpheus.Title = NODE1_TITLE_2;
            morpheus.IsAgent = true;
			JObject props = new JObject();
			foreach (var kvp in morpheus.GetProperties())
			{
				props.Add(kvp.Key, new JValue(kvp.Value));
			}
			jsonServices.SetNodeProperties(morpheus.Id, props);

            //get node and validate changed properties
            JObject jObject = jsonServices.GetNode(morpheus.Id);
            Assert.AreEqual(jObject.Count, 12);
            JToken token;
            jObject.TryGetValue("data", out token);
            Assert.IsNotNull(token);
            Assert.AreEqual(token.Count(), 4);
            Assert.AreEqual(token[MatrixPerson.NAME].Value<string>(), morpheus.Name);
            Assert.AreEqual(token[MatrixPerson.TITLE].Value<string>(), morpheus.Title);
            Assert.AreEqual(token[MatrixPerson.ISHUMAN].Value<bool>(), morpheus.IsHuman);
            Assert.AreEqual(token[MatrixPerson.ISAGENT].Value<bool>(), morpheus.IsAgent);
        }

        [Test]
        public void GetNodeProperties()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);
        }

        [Test]
        public void RemoveNodePropertiesById()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //now clear properties and validate they are cleared
            jsonServices.RemoveNodeProperties(morpheus.Id);
            JObject jObject = jsonServices.GetNodeProperties(morpheus.Id);
            Assert.IsTrue(jObject.Count == 0);         
        }

        [Test]
        [Ignore]
        public void SetNodeProperty()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //now change a property
            jsonServices.SetNodeProperty(morpheus.Id, Person.TITLE, NODE1_TITLE_2);
            morpheus.Title = NODE1_TITLE_2;

            //get person and validate properties are correct
            JObject jObject = jsonServices.GetNodeProperties(morpheus.Id);            
            Assert.AreEqual(jObject.Count, 4);
            Assert.AreEqual(jObject[MatrixPerson.NAME].Value<string>(), morpheus.Name);
            Assert.AreEqual(jObject[MatrixPerson.TITLE].Value<string>(), morpheus.Title);
            Assert.AreEqual(jObject[MatrixPerson.ISHUMAN].Value<bool>(), morpheus.IsHuman);
            Assert.AreEqual(jObject[MatrixPerson.ISAGENT].Value<bool>(), morpheus.IsAgent);
        }

        [Test]
        public void GetNodeProperty()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //get props and validate
            string name = jsonServices.GetNodeProperty(morpheus.Id, MatrixPerson.NAME);
            string title = jsonServices.GetNodeProperty(morpheus.Id, MatrixPerson.TITLE);
            Assert.AreEqual(name, morpheus.Name);
            Assert.AreEqual(title, morpheus.Title);
        }

        [Test]
        public void RemoveNodeProperty()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            //remove nodes and validate
            jsonServices.RemoveNodeProperty(morpheus.Id, MatrixPerson.TITLE);
            JObject jObject = jsonServices.GetNodeProperties(morpheus.Id);
            Assert.AreEqual(jObject.Count, 3);
            JToken jToken;
            Assert.IsFalse(jObject.TryGetValue("Title", out jToken));
            Assert.AreEqual(jObject[MatrixPerson.NAME].Value<string>(), morpheus.Name);            
            Assert.AreEqual(jObject[MatrixPerson.ISHUMAN].Value<bool>(), morpheus.IsHuman);
            Assert.AreEqual(jObject[MatrixPerson.ISAGENT].Value<bool>(), morpheus.IsAgent);

            //remove another node and validate
            jsonServices.RemoveNodeProperty(morpheus.Id, MatrixPerson.NAME);
            jObject = jsonServices.GetNodeProperties(morpheus.Id);
            Assert.AreEqual(jObject.Count, 2);
            jToken = null;
            Assert.IsFalse(jObject.TryGetValue("Title", out jToken));
            Assert.IsFalse(jObject.TryGetValue("Name", out jToken));
            Assert.AreEqual(jObject[MatrixPerson.ISHUMAN].Value<bool>(), morpheus.IsHuman);
            Assert.AreEqual(jObject[MatrixPerson.ISAGENT].Value<bool>(), morpheus.IsAgent);
        }

        [Test]
		[ExpectedException(typeof(Neo4jRestException))]
        public void RemoveNode()
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //create node, then get node
            MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);

            //validate node against its stored properties
            ValidatePropertiesOnNode(morpheus);

            jsonServices.DeleteNode(morpheus.Id);

			//Eat it, eat it, eat it, eat it...If it's gettin' cold, reheat it
			jsonServices.GetNode(morpheus.Id);
        }

		[Test]
		public void CreateRelationship()
		{
			MatrixPerson morpheus;
			MatrixPerson neo;
			CreateTwoPeopleWithRelationships(out morpheus, out neo);
		}

		[Test]		
        public void SetRelationshipProperties()
        {
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			//create 2 nodes, then get both nodes
			MatrixPerson morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);
			MatrixPerson neo = this.CreatePerson<MatrixPerson>(NODE2_NAME, NODE2_TITLE);

			//create link from morpheus to neo
			string json = "{\"to\": \"http://localhost:9999/node/" + neo.Id + "\", \"type\": \"Knows\"}";

			JObject jObject = jsonServices.CreateRelationship(morpheus.Id, JObject.Parse(json));
			Assert.AreEqual(jObject.Count, 7);
			Assert.AreEqual(new Uri(jObject["start"].Value<string>()).Segments[2], morpheus.Id.ToString());
			Assert.AreEqual(new Uri(jObject["end"].Value<string>()).Segments[2], neo.Id.ToString());
			Assert.AreEqual(jObject["type"].Value<string>(), "Knows");
			Assert.AreEqual(jObject["data"].Value<JToken>().Count(), 0);
			string MtoNid = new Uri(jObject["self"].Value<string>()).Segments[2];

			//create link from neo to morpheus
			json = "{\"to\": \"http://localhost:9999/node/" + morpheus.Id + "\", \"type\": \"Knows\"}";
			jObject = jsonServices.CreateRelationship(neo.Id, JObject.Parse(json));
			Assert.AreEqual(jObject.Count, 7);
			Assert.AreEqual(new Uri(jObject["start"].Value<string>()).Segments[2], neo.Id.ToString());
			Assert.AreEqual(new Uri(jObject["end"].Value<string>()).Segments[2], morpheus.Id.ToString());
			Assert.AreEqual(jObject["type"].Value<string>(), "Knows");
			Assert.AreEqual(jObject["data"].Value<JToken>().Count(), 0);
			string NtoMid = new Uri(jObject["self"].Value<string>()).Segments[2];

			//set and validate properties on relationship from M to N
			string propData = "{ \"action\": \"Gave the red pill\" }";
			JToken jToken = JObject.Parse(propData);
			jsonServices.SetRelationshipProperties(int.Parse(MtoNid), jToken);
			JArray jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			Assert.AreEqual(jArray.Count, 1);
			Assert.AreEqual(jArray[0]["data"].Value<JToken>()["action"].Value<string>(), "Gave the red pill");

			//set and validate properties on relationship from M to N
			propData = "{ \"action\": \"Took the red pill\" }";
			jToken = JObject.Parse(propData);
			jsonServices.SetRelationshipProperties(int.Parse(NtoMid), jToken);
			jArray = jsonServices.GetRelationshipsOnNode(neo.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			Assert.AreEqual(jArray.Count, 1);
			Assert.AreEqual(jArray[0]["data"].Value<JToken>()["action"].Value<string>(), "Took the red pill");
        }

        [Test]		
        public void GetRelationshipProperties()
        {
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			MatrixPerson morpheus;
			MatrixPerson neo;
			CreateTwoPeopleWithRelationships(out morpheus, out neo);

			//validate props on morpheus
			JArray jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			foreach (var rel in jArray)
			{
				JObject jObject = jsonServices.GetRelationshipProperties(int.Parse(new Uri(rel["self"].Value<string>()).Segments[2]));
				if (jObject.Count > 0)
				{
					Assert.AreEqual(rel["data"].Value<JToken>()["action"].Value<string>(), jObject["action"].Value<string>());
				}
			}

			//validate props on neo
			jArray = jsonServices.GetRelationshipsOnNode(neo.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			foreach (var rel in jArray)
			{
				JObject jObject = jsonServices.GetRelationshipProperties(int.Parse(new Uri(rel["self"].Value<string>()).Segments[2]));
				if (jObject.Count > 0)
				{
					Assert.AreEqual(rel["data"].Value<JToken>()["action"].Value<string>(), jObject["action"].Value<string>());
				}
			}
        }

        [Test]
        public void RemoveRelationshipProperties()
        {
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			MatrixPerson morpheus;
			MatrixPerson neo;
			CreateTwoPeopleWithRelationships(out morpheus, out neo);

			//validate props on morpheus
			JArray jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			foreach (var rel in jArray)
			{
				//make sure we have props
				int relId = int.Parse(new Uri(rel["self"].Value<string>()).Segments[2]);
				JObject jObject = jsonServices.GetRelationshipProperties(relId);
				if (jObject.Count > 0)
				{
					Assert.AreEqual(rel["data"].Value<JToken>()["action"].Value<string>(), jObject["action"].Value<string>());
				}

				//remove and validate
				jsonServices.RemoveRelationshipProperties(relId);
				jObject = jsonServices.GetRelationshipProperties(relId);
				Assert.IsTrue(jObject.Count == 0);
			}

			//validate props on neo
			jArray = jsonServices.GetRelationshipsOnNode(neo.Id, RelationshipDirection.Out, Enumerable.Empty<string>());
			foreach (var rel in jArray)
			{
				//make sure we have props
				int relId = int.Parse(new Uri(rel["self"].Value<string>()).Segments[2]);
				JObject jObject = jsonServices.GetRelationshipProperties(relId);
				if (jObject.Count > 0)
				{
					Assert.AreEqual(rel["data"].Value<JToken>()["action"].Value<string>(), jObject["action"].Value<string>());
				}

				//remove and validate
				jsonServices.RemoveRelationshipProperties(relId);
				jObject = jsonServices.GetRelationshipProperties(relId);
				Assert.IsTrue(jObject.Count == 0);
			}
        }

        [Test]
		[Ignore]
        public void SetRelationshipProperty()
        {
            throw new NotImplementedException();
        }

        [Test]
		[Ignore]
        public void GetRelationshipProperty()
        {
            throw new NotImplementedException();
        }

		[Test]
		[Ignore]
        public void RemoveRelationshipProperty()
        {
            throw new NotImplementedException();
        }

		[Test]
		public void RemoveRelationship()
		{
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			MatrixPerson morpheus;
			MatrixPerson neo;
			CreateTwoPeopleWithRelationships(out morpheus, out neo);

			//now spin through and delete all relationships on morpheus			
			int count = 2;
			string relId = null;
			JArray jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.All, Enumerable.Empty<string>());
			while (count > 0)
			{
				Assert.AreEqual(jArray.Count, count--);

				//validate we just deleted the correct relationship id
				if (relId != null)
				{
					//make sure last relationship id is NOT in return list of ids
					foreach (JToken jToken in jArray)
					{
						Assert.AreNotEqual(relId, new Uri(jArray[0]["self"].Value<string>()).Segments[2]);
					}
				}

				//delete the relationhsip
				relId = new Uri(jArray[0]["self"].Value<string>()).Segments[2];
				jsonServices.RemoveRelationship(int.Parse(relId));

				//now go get all relationships for morpheus
				jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.All, Enumerable.Empty<string>());
			}

			jArray = jsonServices.GetRelationshipsOnNode(morpheus.Id, RelationshipDirection.All, Enumerable.Empty<string>());
			Assert.IsEmpty(jArray);
		}

		[Test]
		public void GetRelationshipsOnNode()
		{
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			MatrixPerson morpheus;
			MatrixPerson neo;
			CreateTwoPeopleWithRelationships(out morpheus, out neo);

			//get ids of two folks
			int[] ids = new int[] {morpheus.Id, neo.Id};

			//TEST MATRIX (ha ha ha)            
			JObject jObject = null;
			JArray jArray = null;
			//test for each type of RelationshipDirection            
			foreach (var relDir in Enums.Get<RelationshipDirection>())
			{
				//Test for all relationship types via empty types enum
				//var relTypes = Enumerable.Empty<RelationshipType>();
				//foreach (int startId in ids)
				//{
				//    json = restServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
				//    ValidateRelationshipJson(json, startId, ids, relDir, relTypes);
				//}

				//Test for all relationship types
				var relTypes = Enums.Get<RelationshipType>();
				foreach (int startId in ids)
				{
					jArray = jsonServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
					ValidateRelationshipJson(jArray, startId, ids, relDir, relTypes);
				}

				//Test for all relationship types Knows, Recruited
				relTypes = Enums.Get<RelationshipType>().Where(rt => rt == RelationshipType.Knows || rt == RelationshipType.Recruited);
				foreach (int startId in ids)
				{
					jArray = jsonServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
					ValidateRelationshipJson(jArray, startId, ids, relDir, relTypes);
				}

				//Test for all relationship types Knows, WorksFor
				relTypes = Enums.Get<RelationshipType>().Where(rt => rt == RelationshipType.Knows || rt == RelationshipType.WorksFor);
				foreach (int startId in ids)
				{
					jArray = jsonServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
					ValidateRelationshipJson(jArray, startId, ids, relDir, relTypes);
				}

				//Test for all relationship types Recruited, WorksFor
				relTypes = Enums.Get<RelationshipType>().Where(rt => rt == RelationshipType.Recruited || rt == RelationshipType.WorksFor);
				foreach (int startId in ids)
				{
					jArray = jsonServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
					ValidateRelationshipJson(jArray, startId, ids, relDir, relTypes);
				}

				foreach (var relationshipType in Enums.Get<RelationshipType>())
				{
					//Test single relationship type
					foreach (int startId in ids)
					{
						jArray = jsonServices.GetRelationshipsOnNode(startId, relDir, relTypes.Select(e => e.ToString()));
						ValidateRelationshipJson(jArray, startId, ids, relDir, relTypes);
					}
				}
			}
		}

    	private void CreateTwoPeopleWithRelationships(out MatrixPerson morpheus, out MatrixPerson neo)
		{
			NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

			//create 2 nodes, then get both nodes
			morpheus = this.CreatePerson<MatrixPerson>(NODE1_NAME, NODE1_TITLE);
			neo = this.CreatePerson<MatrixPerson>(NODE2_NAME, NODE2_TITLE);

			JObject jObject = new JObject();
			jObject.Add("to", new JValue(neo.SelfUri.AbsoluteUri));

			JObject relProps = new JObject();
			relProps.Add("action", new JValue("Gave the red pill"));

			jObject.Add("data", relProps);
			jObject.Add("type", new JValue(RelationshipType.Knows.ToString()));
			JObject MtoN = jsonServices.CreateRelationship(morpheus.Id, jObject);
			Assert.AreEqual(MtoN.Count, 7);
			Assert.AreEqual(new Uri(MtoN["start"].Value<string>()).Segments[2], morpheus.Id.ToString());
			Assert.AreEqual(new Uri(MtoN["end"].Value<string>()).Segments[2], neo.Id.ToString());
			Assert.AreEqual(MtoN["type"].Value<string>(), "Knows");

			jObject = new JObject();
			jObject.Add("to", new JValue(morpheus.SelfUri.AbsoluteUri));

			relProps = new JObject();
			relProps.Add("action", new JValue("Took the red pill"));

			jObject.Add("data", relProps);
			jObject.Add("type", new JValue(RelationshipType.Knows.ToString()));
			JObject NtoM = jsonServices.CreateRelationship(neo.Id, jObject);
			Assert.AreEqual(NtoM.Count, 7);
			Assert.AreEqual(new Uri(NtoM["start"].Value<string>()).Segments[2], neo.Id.ToString());
			Assert.AreEqual(new Uri(NtoM["end"].Value<string>()).Segments[2], morpheus.Id.ToString());
			Assert.AreEqual(NtoM["type"].Value<string>(), "Knows");
		}

		private void ValidateRelationshipJson(JArray jArray, int start, int[] ids, RelationshipDirection relDir, IEnumerable<RelationshipType> relTypes)
		{
			Dictionary<string, string> testValues = new Dictionary<string, string>();

			foreach (RelationshipType relType in relTypes)
			{
				switch (relType)
				{
					case RelationshipType.Knows:
						if (relDir == RelationshipDirection.All
							|| (start == ids[0] && relDir == RelationshipDirection.Out)
							|| (start == ids[1] && relDir == RelationshipDirection.In))
						{
							testValues.Add(string.Format("{0}|{1}|Knows", ids[0], ids[1]), "action|Gave the red pill");
						}
						if (relDir == RelationshipDirection.All
							|| (start == ids[1] && relDir == RelationshipDirection.Out)
							|| (start == ids[0] && relDir == RelationshipDirection.In))
						{
							testValues.Add(string.Format("{1}|{0}|Knows", ids[0], ids[1]), "action|Took the red pill");
						}
						break;
				}
			}
			
			Assert.AreEqual(jArray.Count, testValues.Count);
			foreach (JToken token in jArray)
			{
				string startId = new Uri(token["start"].Value<string>()).Segments[2];
				string endId = new Uri(token["end"].Value<string>()).Segments[2];
				string action = token["type"].Value<string>();
				string key = startId + "|" + endId + "|" + action;
				string[] testData = testValues[key].Split('|');
				JToken dataToken = token["data"].Value<JToken>();
				if (testData.Length == 1 && string.IsNullOrWhiteSpace(testData[0]))
				{
					Assert.IsNull(dataToken.First);
				}
				else
				{
					Assert.AreEqual(dataToken[testData[0]].Value<string>(), testData[1]);
				}
			}
		}

    	private void ValidatePropertiesOnNode(Person person)
        {
            NodeJsonServices jsonServices = new NodeJsonServices(neo4jRestUri);

            //get person properties by id and validate properties against source object
            JObject jObject = jsonServices.GetNodeProperties(person.Id);            
            MatrixPerson mp = person as MatrixPerson;
            if (mp == null)
            {
                Assert.AreEqual(jObject.Count, 2);
                Assert.AreEqual(jObject[MatrixPerson.NAME].Value<string>(), person.Name);
                Assert.AreEqual(jObject[MatrixPerson.TITLE].Value<string>(), person.Title);
            }
            else
            {
                Assert.AreEqual(jObject.Count, 4);
                Assert.AreEqual(jObject[MatrixPerson.NAME].Value<string>(), mp.Name);
                Assert.AreEqual(jObject[MatrixPerson.TITLE].Value<string>(), mp.Title);
                Assert.AreEqual(jObject[MatrixPerson.ISHUMAN].Value<bool>(), mp.IsHuman);
                Assert.AreEqual(jObject[MatrixPerson.ISAGENT].Value<bool>(), mp.IsAgent);
            }
        }
    } 
}
